 
// import { StationNetwork } from "GameLoop/Path/StationNetwork";
import { PositionHelper } from "utils/position/PositionHelper";
 


// import { MY_CONTROLLER_STRUCTURES, SitePriority } from "Autoplanning/Autoplainning";
export  var SitePriority: string[] = [
    "spawn",
    "extension",
    "container",

    "storage",
    "terminal",

    "link",
    "road",
    "tower",
    "lab",
    "extractor",
    "factory",
    "observer",
    "powerSpawn",
    "nuker",
    "constructedWall",
    "rampart",
];
 
export  var MY_CONTROLLER_STRUCTURES: { [Key: string]: { [key2: number]: number } } = {
    "spawn":  { 0: 0 , 1: 1 , 2: 1 , 3: 1 , 4: 1 , 5: 1 , 6: 1 , 7: 2 , 8: 3 },
     "extension": {0: 0,1: 0,2: 5,3:10,4: 20,5: 30,6: 40,7:50,8:60},
    "link": {0: 0,1: 0,2: 0,3: 0,4:0,5:2,6: 3,7: 4,8: 6},
    "road":{0:0,1:0,2:0,3:0,4:24,5:24,6:24,7:2500,8:2500},
    "constructedWall":{0: 0,1:0,2:2500,3:2500,4:2500,5:2500,6:2500,7:2500,8:2500},
    "rampart": {0: 0,1:0,2:0,3:0,4:0,5:0,6:2500,7:2500,8:2500},
    "storage":{0: 0,1:0,2:0,3:0,4:1,5:1,6:1,7:1,8:1},
    "tower": {0: 0,1:0,2:0,3:1,4:1,5:2,6:2,7:3,8:6},
    "observer": {0: 0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:1},
    "powerSpawn": {0: 0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:1},
    "extractor": {0: 0,1:0,2:0,3:0,4:0,5:0,6:1,7:1,8:1},
    "terminal": {0: 0,1:0,2:0,3:0,4:0,5:0,6:1,7:1,8:1},
    "lab": {0: 0,1:0,2:0,3:0,4:0,5:0,6:3,7:6,8:10},
    "container": {0:0,1:0,2:5,3:5,4:5,5:5,6:5,7:5,8:5},
    "nuker": {0: 0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:1},
    "factory": {0: 0,1:0,2:0,3:0,4:0,5:0,6:0,7:1,8:1}};
 
export class AutoPlanManager
{
     private static  SpawnModuleExtensionMap:{[key in number]:{[key in number]:IFVector2[]}}={
        2:{
            2: [ {x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:1,y:0} ],
            4: [ {x:0,y:-1},{x:-1,y:0},{x:-1,y:1},{x:0,y:1} ]
            },
        4:{
            2: [ {x:0,y:-1},{x:1,y:-1},{x:0,y:1}  ],
            4: [ {x:-1,y:0},{x:1,y:0},{x:0,y:1},{x:1,y:1} ]
            }
    };
    // type ModuleType = "source"|"minerial"|"controller"|"spawn"|"labs"|"core"|"rampart"|"room"
    private static ModulePriority:ModuleType[]=["spawn","source","core","controller","labs","room","labs","minerial","rampart"];

    private static RoomSitePlans:{[roomName:string]:ISiteQueue} = {};
    static RoomPlans:{[roomName:string]:IModulePlan[]} = {};
    // 存储每个房间的模块
    // 添加房间Plan


    /**
     * 普通房间建筑
    */
     static AddRoomPlan(roomName:string,moduleplan:IModulePlan[])
     {
        const roomname = roomName;
        {
            // 去除掉控制器的container.Link也可能重新计算
            let idx = _.findIndex(moduleplan,e=>e.type.startsWith("controller"));
            if(idx>-1)
            {
                    moduleplan[idx].structures[  "container"]=[];
            }
        }
        this.ExtendModuleContainer(moduleplan);
        const sitequeue = AutoPlanManager.GenerateRoomPlan(moduleplan);
        const plan:IPlanStrategy={roomName:roomname,ModulePlan:moduleplan,SiteQueue:sitequeue};
         // 调用已有的模块生成额外的模块
         // 注册寻路的costmatrix
        plan.ModulePlan = AutoPlanManager.ExtendRoomPlan(plan.ModulePlan);
        this.RegisterRoomConstructure(roomname,moduleplan);
        return plan;
     }
     static AddRoomFastPlan(roomName:string,moduleplan:IModulePlan[])
     {
         const roomname = roomName;
         const sitequeue = AutoPlanManager.GenerateFastRoomPlan(moduleplan);
         const plan:IPlanStrategy={roomName:roomname,ModulePlan:moduleplan,SiteQueue:sitequeue};
         // 调用已有的模块生成额外的模块
         // 注册寻路的costmatrix
      
         return plan;
     }
     /**
      * lab模块和mine模块拓展增加container
      * @param moduleplans 
      */
     private static ExtendModuleContainer(moduleplans:IModulePlan[])
     {
        for(const item of moduleplans)
        {
            if (item.type.startsWith("source"))
            {
               const poss = item.structures[ "road"];
               for(const e of poss)
               {
                   if(PositionHelper.getDistance(e,item.pos)==1)
                   {
                       item.structures["container"] = [e];
                       break;
                   }
               }
               // 拓展container
            }
            else if (item.type.startsWith("lab"))
            {
               // 拓展container
               item.structures["container"] = [{x:item.pos.x+1,y:item.pos.y+1}];
            }
            else if (item.type.startsWith("controller"))
            {
                item.structures["link"]=[];
            }
        }
     }
     public static ExtendRoomPlan(moduleplans:IModulePlan[])
     {
         const extendPlans:IModulePlan[] = [];
         for(const item of moduleplans)
         {
             if(item.type.startsWith( "room"))
             {
                //  const ramparts= item.structures[STRUCTURE_RAMPART];
                //  const planrampart:IModulePlan = {type:STRUCTURE_RAMPART,pos:{x:0,y:0},structures:{[STRUCTURE_RAMPART]:ramparts}};
                //  extendPlans.push(planrampart);

                 const observe= item.structures["observer"];
                 const planobserve:IModulePlan = {type:"observer",pos:{x:0,y:0},structures:{["observer"]:observe}};
                 extendPlans.push(planobserve);

                 const tower= item.structures["tower"];
                 const plantower:IModulePlan = {type:"tower",pos:{x:0,y:0},structures:{["tower"]:tower}};
                 extendPlans.push(plantower);
             }
 
         }
         return  moduleplans.concat(extendPlans);
     }

    /**
     * 根据IModulePlan[] 生成建设队列
     * @param IModulePlan[]
     * @returns {ISiteQueue}
    */
     private static GenerateRoomPlan( moduleplan:IModulePlan[]):ISiteQueue
     {
         const ModulePlans = _.cloneDeep(moduleplan);
         // 1.建设矿模块的extension
         // 2.建设Spawn模块的extension 和container 根据坐标区域
         // 3.余下的按照模块类型建设，优先建设Spawn模块->矿模块->中心模块
         // SitePriority
         const AllStructures:{[key in string]:IFVector2[]}={
             "spawn": [],
             "extension": [],
             "link":[],
             "road":[],
             "constructedWall":[],
             "rampart": [],
             "storage":[],
             "tower": [],
             "observer": [],
             "powerSpawn": [],
             "extractor": [],
             "terminal": [],
             "lab": [],
             "container": [],
             "nuker": [],
             "factory": []};
             // 1.ext

             {

                     // b.Spawn模块的extension
                 const spawnmodule = ModulePlans.find(item=>item.type.startsWith("spawn"));
                 if(spawnmodule)
                 {
                     // 根据basepos计算extension的位置
                     const basepos = spawnmodule.pos;
                     const arr=[{x:2,y:2},{x:2,y:4},{x:4,y:2},{x:4,y:4}]
                     for( const item of arr)
                     {
                         const posArr = AutoPlanManager.SpawnModuleExtensionMap[item.x][item.y];
                         const x =item.x;
                         const y = item.y;
                         const relativepos = {x:basepos.x+x,y:basepos.y+y};
                         const extposs =  _.map(posArr,item=>{return  {x:relativepos.x+item.x,y:relativepos.y+item.y}})
                         AllStructures["extension"].push(...extposs);

                         const index = spawnmodule.structures["road"].findIndex(e=>e.x== relativepos.x && e.y ==relativepos.y);
                         spawnmodule.structures["road"].splice(index,1);
                     }

                     spawnmodule.structures["extension"] = [];
                 }

             // a.矿石模块的extension
             const mindmodules = ModulePlans.filter(item=>item.type.startsWith("source"));
             for(const module of mindmodules)
             {
                 const extension = module.structures["extension"];
                 if(extension)
                 {
                     AllStructures["extension"].push(...extension);
                     module.structures["extension"]=[];
                 }
             }


             // c.room模块的extension
             const roommodule = ModulePlans.find(item=>item.type.startsWith("room"));
             if(roommodule)
             {
                 const extension = roommodule.structures["extension"];
                 if(extension)
                 {
                     for(const pos of extension)
                     {
                         AllStructures["extension"].push(pos);
                     }
                     roommodule.structures["extension"] = [];
                 }
             }
             // ext就没了
         }
         {
            // container,先放spawn的，再放core的，最后source的
            const spawnmodule = ModulePlans.find(item=>item.type.startsWith("spawn"));
            if(spawnmodule)
            {
                AllStructures["container"].push(...spawnmodule.structures['container']);
                spawnmodule.structures['container']=[]
            }
            const coremodule = ModulePlans.find(item=>item.type.startsWith("core"));
            if(coremodule && coremodule.structures['container'])
            {
                AllStructures["container"].push(...coremodule.structures['container']);
                coremodule.structures['container']=[]
            }
         }
         // 2.Lab先放中间的两个
         {
             const labmodule = ModulePlans.find(item=>item.type.startsWith("lab"));
             if(labmodule)
             {
                 const labpos=labmodule.structures["lab"];
                     [labpos[0],labpos[4]] =  [labpos[4],labpos[0]];
                     [labpos[1],labpos[5]] =  [labpos[5],labpos[1]];
             }
         }

         // 3.接下来按照顺序处理除extension之外的所有模块
         for(const structuretype of SitePriority)
         {

             for(const moduletype of AutoPlanManager.ModulePriority)
             {
                 const findModules = ModulePlans.filter(item=>item.type.startsWith(moduletype));
                 for(const findModule of findModules)
                 {
                     if(findModule)
                     {
                         const curstrcutuePos = findModule.structures[structuretype];
                         if(curstrcutuePos)
                         {
                         AllStructures[structuretype].push(...curstrcutuePos);
                         findModule.structures[structuretype]=[];
                         }

                     }
                     else
                     {
                         console.log("ERROR 找不到模块 type:"+moduletype);
                     }
                 }

             }
         }

         return  this.GenerateSiteQueue(AllStructures);
     }

/**
     * 根据IModulePlan[] 生成建设队列
     * @param IModulePlan[]
     * @returns {ISiteQueue}
    */
 private static GenerateFastRoomPlan( moduleplan:IModulePlan[]):ISiteQueue
 {
     const ModulePlans = _.cloneDeep(moduleplan);
     // 1.建设矿模块的extension
     // 2.建设Spawn模块的extension 和container 根据坐标区域
     // 3.余下的按照模块类型建设，优先建设Spawn模块->矿模块->中心模块
     // SitePriority
     const AllStructures:{[key in string]:IFVector2[]}={
         "spawn": [],
         "extension": [],
         "link":[],
         "road":[],
         "constructedWall":[],
         "rampart": [],
         "storage":[],
         "tower": [],
         "observer": [],
         "powerSpawn": [],
         "extractor": [],
         "terminal": [],
         "lab": [],
         "container": [],
         "nuker": [],
         "factory": []};
         // 1.ext
 
     // 3.接下来按照顺序处理除extension之外的所有模块
     for(const structuretype of SitePriority)
     {
        for(const findModule of ModulePlans)
        {
            const curstrcutuePos = findModule.structures[structuretype];
            if(curstrcutuePos)
            {
                AllStructures[structuretype].push(...curstrcutuePos);
                findModule.structures[structuretype]=[];
            }
        }
     }

     return  this.GenerateSiteQueue(AllStructures);
 }
    /**
     *
    */
    private static GenerateSiteQueue(AllStructures:{[key in string]:IFVector2[]}):ISiteQueue
    {
        // JSON.stringify(Memory.Data.entity._entityTable.W1N8.AutoPlanStrategy[0].planStrategy.normal.SiteQueue);
        const sitequeue ={items:new Array<IPlanItem>(),levelLimit:new Array<number>(10),index:0}
        const AllPlans :IPlanItem[]=[];

        const pick=(count:number,structuretype:BuildableStructureConstant,structues:{[key in string]:IFVector2[]}):IPlanItem[] =>
        {
            const structures = structues[structuretype];
            const child = structures.splice(0,count);
            return _.map(child,item=>{return {type:structuretype,pos:item}});
        }

        for(let level=0;level<=8;level++)
        {
            for(const structuretype of SitePriority)
            {
                const structureCountLimit =MY_CONTROLLER_STRUCTURES[structuretype];
                const structurecount =  structureCountLimit[level+1]-structureCountLimit[level];
                if(structurecount ==0)
                {
                    continue;
                }
                const planitems =  pick(structurecount,structuretype as BuildableStructureConstant,AllStructures)
                AllPlans.push(...planitems);
            }
            sitequeue.levelLimit[level+1]= AllPlans.length;
        }
        sitequeue.items = AllPlans;
        return sitequeue;
    }

    public static RegisterRoomConstructure(roomName:string,moduleplans:IModulePlan[])
    {
        const excludety=["container","road","rampart"];
        const matrix = new PathFinder.CostMatrix();
        for(const moduleplan of moduleplans)
        {
           for(const structuretype in moduleplan.structures)
           {
               if(excludety.findIndex(item=>item == structuretype)>=0)
               {
                continue;
               }
               const structures = moduleplan.structures[structuretype];
               for(const structure of structures)
               {
                    matrix.set(structure.x,structure.y,0xff);
               }
           }
        }
       // StationNetwork.getInstance.PathFinder.RegisterRoomMatrix(roomName,matrix);
    }
}
